home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 054a / wpjv1n5.zip / WPJV1N5.TXT < prev   
Text File  |  1993-05-08  |  87KB  |  2,166 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.          WW     WW     WW      PPPPPPPP              JJ
  8.          WW     WW     WW      PP    PP              JJ
  9.           WW   WWWW   WW       PP    PP              JJ
  10.           WW  WW  WW  WW       PPPPPPPP              JJ
  11.           WW  WW  WW  WW       PP             JJ     JJ
  12.            WWWW    WWWW        PP              JJ   JJ
  13.             WW      WW         PP               JJJJJ
  14.  
  15.      ----------------------------------------------------------------
  16.      The Windows Programmer's Journal                       Volume 01
  17.      Copyright 1993 by Peter J. Davis                       Number 05
  18.      and Mike Wallace                                          May 93
  19.      ----------------------------------------------------------------
  20.      A monthly forum for novice-advanced programmers to share ideas and concepts
  21.      about programming in the Windows (tm) environment.   Each issue is uploaded
  22.      to  the info  systems  listed below  on the  first of  the month,  but made
  23.      available at the convenience of the sysops, so allow for a couple of days.
  24.  
  25.      You can get in touch with the editors via Internet or Bitnet at:
  26.  
  27.      HJ647C at GWUVM.BITNET   or   HJ647C at GWUVM.GWU.EDU  (Pete)
  28.  
  29.      CompuServe: 71141,2071 (Mike)
  30.  
  31.      GEnie: P.DAVIS5
  32.  
  33.      or you can send paper mail to:
  34.  
  35.      Windows Programmer's Journal
  36.      9436 Mirror Pond Dr.
  37.      Fairfax, Va. 22032
  38.  
  39.      We can also be reached by phone at: (703) 503-3165.
  40.  
  41.      The WPJ BBS can be reached at: (703) 503-3021.
  42.  
  43.      The WPJ  BBS is currently 2400 Baud (8N1). We'll  be going to 14,400 in the
  44.      near future, we hope.
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.                                      LEGAL STUFF
  54.  
  55.  
  56.      - Microsoft, MS-DOS, Microsoft Windows, Windows NT, Windows for Workgroups,
  57.      Windows for Pen Computing,  Win32, and Win32S are registered  trademarks of
  58.      Microsoft Corporation.
  59.  
  60.      - Turbo  Pascal for  Windows, Turbo  C++ for Windows,  and Borland  C++ for
  61.      Windows are registered trademarks of Borland International.
  62.  
  63.      - WordPerfect is a registered trademark of WordPerfect Corporation.
  64.  
  65.      -  Other trademarks mentioned herein  are the property  of their respective
  66.      owners.
  67.  
  68.      -  WPJ  is  available  from  the  WINSDK,  WINADV  and  MSWIN32  forums  on
  69.      CompuServe, and the IBMPC, WINDOWS and BORLAND forums on Genie.  It is also
  70.      available on America Online in the Programming library.   On Internet, it's
  71.      available on WSMR-SIMTEL20.ARMY.MIL and FTP.CICA.INDIANA.EDU.  We upload it
  72.      by  the 1st of each  month and it  is usually available by  the 3rd or 4th,
  73.      depending on when the sysops receive it.
  74.  
  75.      -  The Windows Programmer's Journal takes no responsibility for the content
  76.      of  the   text  within  this  document.  All   text  is  the  property  and
  77.      responsibility of the individual authors. The Windows Programmer's  Journal
  78.      is solely a vehicle for allowing  articles to be collected and  distributed
  79.      in a common and easy to share form. 
  80.  
  81.      -  No part  of  the Windows  Programmer's  Journal may  be re-published  or
  82.      duplicated in  part or whole, except in the complete and unmodified form of
  83.      the Windows Programmer's Journal, without the express written permission of
  84.      each  individual author. The Windows  Programmer's Journal may  not be sold
  85.      for  profit without the express written permission of the Publishers, Peter
  86.      Davis  and  Michael  Wallace,  and  only  then  after  they  have  obtained
  87.      permission from the individual authors.
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.                          Table of Contents
  96.  
  97.      Subject                                        Page  Author(s)
  98.      -----------------------------------------------------------------
  99.      WPJ.INI .......................................  4   Pete Davis
  100.  
  101.      Beginner's Column  ............................  6   Dave Campbell
  102.  
  103.      Creating Windows Text File Editors  ........... 15   Eric Grass
  104.  
  105.      Midlife Crisis: Windows at 32  ................ 20   Pete Davis
  106.  
  107.      WDASM - Review of a Windows Disassembler  ..... 23   Pete Davis
  108.  
  109.      Hypertext, Sex and Winhelp  ................... 25   Loewy Ron
  110.  
  111.      Enhancing the WINSTUB Module  ................. 30   Rodney Brown
  112.  
  113.      Microsoft Developers Network .................. 33   Dave Campbell
  114.  
  115.      Getting in Touch with Us .....................  35   Pete & Mike
  116.  
  117.      Last Page ....................................  36   Mike Wallace
  118.  
  119.  
  120.      Windows Programmer's Journal Staff:
  121.  
  122.      Publishers ......................... Pete Davis and Mike Wallace
  123.      Editor-in-Chief .................... Pete Davis
  124.      Managing Editor .................... Mike Wallace
  125.      Contributing Editor ................ Dave Campbell
  126.                                           
  127.      Contributing Writer ................ Dave Campbell
  128.      Contributing Writer ................ Eric Grass
  129.      Contributing Writer ................ Loewy Ron
  130.      Contributing Writer ................ Rodney Brown
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.                                        WPJ.INI
  141.                                     By Pete Davis
  142.  
  143.           Another  month, another  issue. Wow,  up to  number 5.  I guess  I say
  144.      something  along those  lines  every month,  but  the response  just  keeps
  145.      getting  better  and better  and  I  guess I'm  just  surprised  that we're
  146.      actually getting these things out every month.
  147.  
  148.           I received  some questions from our readers about some of the articles
  149.      in the magazine.  Their concern was  that we seem  to try to  fit a lot  of
  150.      information into  short  articles  and  that sometimes  it's  not  in-depth
  151.      enough.  Well,  to those  who think  that, let  me  explain. When  we write
  152.      articles for the magazine (and I can only speak for me and Mike), we do try
  153.      to fit the  information into rather short  articles and we don't go  into a
  154.      great deal of depth a lot of the time. The reason for this is that Mike and
  155.      I both work  full-time. On top of that, we do  several other things outside
  156.      of work and the magazine. Writing in-depth  articles means lots of research
  157.      and time. We can't afford that kind  of time, unfortunately. It is my  hope
  158.      that, someday, I'll have more time to spend writing more in-depth articles.
  159.      Until that day,  we can  only offer what  we can.  We try to  give as  much
  160.      information as  is  applicable  and  when  a readers  asks  us  to  clarify
  161.      something, we  try our best to  do that. If  you ever feel like  an article
  162.      needs  clarification, let us  know and we'll  either do  that directly, via
  163.      mail, or we'll do an addendum in a future issue.
  164.  
  165.           Next subject: Me!  After the last paragraph,  now's the time  to spill
  166.      the  beans about why  things are going  to be changing  a bit for  me. I am
  167.      going  to  be  writing a  book  for  Addison-Wesley  publishing on  Windows
  168.      programming  (NT and  the 32-bit  stuff). Unlike  the writing  I do  in the
  169.      magazine, the  stuff in the book will be  the kind of writing that requires
  170.      months of research and lots  of checking and double-checking (like  I said,
  171.      we don't have the time to do that for the magazine). Anyway, the book is on
  172.      Win32 programming and it will be in the Andrew Schulman Programming Series.
  173.      I have  to say  I'm awfully excited  about the  whole thing and  I'm really
  174.      looking forward to it. I couldn't possibly thank Andrew Schulman enough for
  175.      the  chance he's giving  me. So, that's  what's up with me.  What does this
  176.      mean? Well, for  one thing, all  of my articles  are going  to be on  Win32
  177.      programming  for the next few months. I've got to do this just to help keep
  178.      my mind trained on the topic, if nothing else. Also, I might not be able to
  179.      do quite as much writing for the magazine as I'd like. 
  180.  
  181.           Also, nothing firm here, but it looks like I might be doing an article
  182.      with Ron Burk of Windows/DOS Developer's Journal. This, like the book, is a
  183.      sort of first for me and I'm really excited about that. I'll give more info
  184.      on this next month, when I know more.
  185.  
  186.           So, that's  what's going on with  me. After the book  is done, perhaps
  187.      I'll start writing about things other  than Win32, but hopefully, by  then,
  188.      EVERYONE  will be  programming in  Win32. It  could happen!  By the  way, I
  189.      expect each and every one of you to buy my book when it's done.
  190.  
  191.           We've got an article by a guy named Eric Grass in this issue. I've got
  192.  
  193.                                         - 4 -
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.      to talk about how I met Eric  for a minute. Eric writes a shareware Windows
  201.      disassembler called WDASM. It's a  really nice product and I felt  I had to
  202.      review it in this issue. Anyway, when I registered WDASM (registration is a
  203.      mere $10, I felt obligated  to pay $20, because it's worth at least that) I
  204.      sent  in  some  suggestions for  expanding  WDASM.  In  our ensuing  e-mail
  205.      volleys, I  asked Eric if he'd  write an article for  the magazine. Anyway,
  206.      read his article  on writing an editor in Windows and read my review of his
  207.      disassembler  and   then  get  his   disassembler!  You'll  thank   me  for
  208.      recommending it and you'll thank Eric for writing it.
  209.  
  210.           The last  thing I  want to  talk about is  submissions. The  number of
  211.      article  submissions seems to  be on the  decline. Unless  we start getting
  212.      more articles, this  magazine might have  to become a bi-monthly  affair. I
  213.      know that I won't have as much time as I'd like to do all the work required
  214.      to keep it monthly. Mike, I'm sure, will  do his best to write for it,  but
  215.      unless we get  more submissions, I can't see us staying  at a monthly pace.
  216.      The final decision  will have to be  Mike's since he  is going to be  stuck
  217.      with doing most of the work for the next few months.
  218.  
  219.           Remember, we don't do this just for us, we do it for you, the readers.
  220.      If  you've felt like  you've gotten something  out of the  magazine, try to
  221.      return the favor and give  a little of your time to help keep  it a monthly
  222.      magazine. I  know a lot of  you want to see  it stay monthly. I  know I do.
  223.      Writing  an article can  take as little  as a few  hours. Most of  you have
  224.      something  you've learned somewhere that  could help a  lot of other people
  225.      out. We're counting on you to share that information.
  226.  
  227.           Until next month, peace.
  228.  
  229.      P.S. I'm writing this the day of the release of this  issue to apologize to
  230.      our readers.  Things have been incredibly  hectic lately for  me because of
  231.      the book and now  this possible article  with Ron Burk.  The timing on  the
  232.      magazine was just off a bit. Mike has also  been really busy, so neither of
  233.      us had  the  time this  month  that we'd  normally  like to  put  into  the
  234.      magazine. Please accept our apologies. 
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.                                         - 5 -
  245.  
  246.  
  247.  
  248.  
  249.  
  250.                                   Beginner's Column
  251.                                    By Dave Campbell
  252.  
  253.      Don't you just hate it  when you look at a ton of Windows Applications, and
  254.      they  all look alike,  and they all do  the same things  in response to the
  255.      same keystrokes, and YOU DON'T HAVE ANY IDEA HOW THEY DID IT?  That's how I
  256.      was about file open dialog boxes. I knew I  could do it, I just didn't want
  257.      to. Yeah, right. So, this month, I am going to give one possible example of
  258.      a way to do  one (the hard way), and along the way, we'll learn some things
  259.      about list boxes.
  260.  
  261.      First I want to pass along a few  things. The code out of which I  stripped
  262.      the file  open dialog  box  uses the  Borland classes  for  the dialog  box
  263.      displays. I have been trying my best to stay away from any compiler-
  264.      particular code for  my articles.  Consequently, I was  mildly taken  aback
  265.      when my dialog box came up with the Borland background in place. How  could
  266.      this be?  Well...I run a background menu processor  that is in Beta at this
  267.      time,  (waiting on documentation), and it  uses the Borland classes.  Since
  268.      that is all instantiated in memory, when our new Hello program came in, and
  269.      tried using  the Borland  calls,  it all  worked.  Basically I  got  lucky.
  270.      Usually it works the  other way. You forget to  put it in, and then  try to
  271.      call it.
  272.  
  273.      My  reason for mentioning  all this is:  if you are  in a debug  cycle, and
  274.      going into and out of Windows relatively often, remember that if you hold a
  275.      shift key down during Windows start-up, you won't get your "run=", "load=",
  276.      or "Startup" files. All you'll get  is Windows, and you can then make  sure
  277.      that if you need a DLL, you load it yourself. 
  278.  
  279.      The second thing is to be sure to read my review of the Microsoft
  280.      Developer's Network  program in this issue. This is like the mother-load of
  281.      Windows help.
  282.  
  283.      Now on to a file open box. What  I want to do is display a dialog  box that
  284.      has a file spec  in it, for example  "*.EXE", and various areas to  display
  285.      paths, and file names,  and directory names, and a way to  select a file or
  286.      quit. That will just about solve  all the requirements (not counting  drag-
  287.      and -drop). How this is implemented in my other application is: in a dialog
  288.      box is a text box requesting a file  name. If OK is selected, and the  file
  289.      name is NULL, then I pop up the file open box. In  Hello, we already have a
  290.      File Open menu choice, and are going to use it.
  291.  
  292.      First let me display what this dlg code looks like:
  293.  
  294.      From Hello.DLG
  295.                    
  296.  
  297.      FILEOPEN DIALOG 80, 60, 148, 101
  298.      STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
  299.      CAPTION "Find File"
  300.      FONT 8, "Helv"
  301.      BEGIN
  302.  
  303.                                         - 6 -
  304.  
  305.  
  306.  
  307.  
  308.  
  309.           CONTROL "File name:", -1, "STATIC" 
  310.            SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 2, 4, 144, 10
  311.           EDITTEXT IDD_FNAME, 2, 14, 144, 12, ES_AUTOHSCROLL
  312.           CONTROL "Files in", -1, "STATIC" 
  313.            SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 2, 30, 38, 12
  314.           CONTROL "", IDD_FPATH, "STATIC" 
  315.            SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 48, 30, 98, 12
  316.           LISTBOX IDD_FLIST, 2, 43, 82, 58, WS_TABSTOP | WS_VSCROLL
  317.           CONTROL "Select", IDOK, "BUTTON", 
  318.            BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP,    
  319.                                                          90,    52,    56,    14
  320.           CONTROL "Cancel", IDCANCEL, "BUTTON", WS_GROUP, 90, 76, 56, 14
  321.  
  322.      The  first new item to  us is the  EDITTEXT line. EDITTEXT  creates a child
  323.      window of  the EDIT class which  gives us a place  to allow a  user to type
  324.      some text for us to  capture. The user may move from edit box  to edit box,
  325.      and  get the focus by clicking the mouse inside it, or we as developers can
  326.      place  the user there. In  our example, we will place  the user in the box.
  327.      When the user sees  a flashing prompt in the  text box, it is safe  to type
  328.      and edit the  typing. As with any Windows text box,  the mouse may be used,
  329.      along with  the backspace key to provide editing features. All this for one
  330.      line in the dialog box!! Isn't it simple to program in Windows?
  331.  
  332.      As with most Windows features,  the parameters are many. The only  one used
  333.      in this example is  ES_AUTOHSCROLL. This does exactly what  it sounds like.
  334.      If the text scrolls beyond the right-hand margin during input, the box will
  335.      scroll with it. The default options are: ES_LEFT | WS_BORDER | WS_TABSTOP.
  336.  
  337.  
  338.      LISTBOX
  339.             
  340.  
  341.      The next new control  is LISTBOX. A listbox is a  child window containing a
  342.      list of character strings, allowing the user to scroll and make selections.
  343.      When a  string is selected with  a mouse click, the  string is highlighted,
  344.      and a message sent to the parent  window. I have chosen to allow a vertical
  345.      scrollbar  on our listbox, and adding it to  the style list is all it takes
  346.      to do that.
  347.  
  348.      Invoking the dialog  box is the easy part. In place of the message handling
  349.      of last month in response to the File Open menu, we'll do:
  350.  
  351.      if (DoFileOpenDlg(hInst, hWnd, &of))
  352.         lstrcpy(OutMsg, (char far *)pof->szPathName);
  353.  
  354.      Notice the  file open dialog  box is embedded in  an if statement.  In this
  355.      circumstance, we  are going  to check  the return value  of the  dialog box
  356.      ourselves, and  if we return  TRUE, we know  we have a  good value  for the
  357.      file, and we display it in the same manner the other data is displayed from
  358.      last month.
  359.  
  360.      Don't be confused as to the parameters passed in this statement.
  361.  
  362.                                         - 7 -
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369.      'DoFileOpenDlg ' is  NOT a dialog box  call. This is simply a  launcher for
  370.      the dialog box that we are setting up  with some parameters, and from which
  371.      we are going to get a return value.
  372.  
  373.      The real dialog  box code inside DoFileOpenDlg looks like  our dialog boxes
  374.      from the last two issues:
  375.  
  376.      lpfnFileOpenDlgProc  =  MakeProcInstance((FARPROC)FileOpenDlgProc,  hInst);
  377.      iReturn = DialogBox(hInst, "FileOpen", hWnd, lpfnFileOpenDlgProc);
  378.      FreeProcInstance(lpfnFileOpenDlgProc);
  379.  
  380.      The only difference here is picking up the return value from 'DialogBox'. 
  381.  
  382.  
  383.      OFSTRUCT
  384.              
  385.  
  386.      At this point, however, I need to discuss one of the parameters to
  387.      DoFileOpenDlg, and that is  &of. of is  listed way up  in the beginning  of
  388.      Hello.C as being of type OFSTRUCT. OFSTRUCT is defined as:
  389.  
  390.      typedef struct tagOFSTRUCT {    /* of */
  391.         BYTE  cBytes;
  392.         BYTE  fFixedDisk;
  393.         UINT  nErrCode;
  394.         BYTE  reserved[4];
  395.         BYTE  szPathName[128];
  396.      } OFSTRUCT;
  397.  
  398.      This  structure is  the result  of opening  a file.  As you  can  see, this
  399.      structure tells us  if the file is  on a hard disk,  if there was an  error
  400.      opening the file, and the complete pathspec for the file.
  401.  
  402.  
  403.      DoFileOpenDlg
  404.                   
  405.  
  406.      Inside DoFileOpenDlg, a few global variables are set:
  407.  
  408.      pof = pofIn;
  409.      lstrcpy(szFileSpec, "*.EXE");
  410.      lstrcpy(szDefExt,   "EXE");
  411.      wFileAttr = DDL_DRIVES | DDL_DIRECTORY;
  412.  
  413.      1) 'pof' is defined above with of as an LPOFSTRUCT 
  414.                                              (or Long Pointer  to an  OFSTRUCT).
  415.      2) *.EXE is picked as the default filespec (to begin with).  
  416.      3) the default file extension of EXE is set.  
  417.      4) the global file attribute variable, wFileAttr is set to 
  418.         DDL_DRIVES | DDL_DIRECTORY  which declares that we are interested  in   
  419.      files that are drive or directory names (to begin with).
  420.  
  421.  
  422.                                         - 8 -
  423.  
  424.  
  425.  
  426.  
  427.  
  428.  
  429.      Windows message Loop
  430.                          
  431.  
  432.      With all that out of the way, let's start with the WM_INITDIALOG case:
  433.  
  434.         case WM_INITDIALOG :
  435.            SendDlgItemMessage(hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L);
  436.            DlgDirList(hDlg, szFileSpec, IDD_FLIST, IDD_FPATH,  wFileAttr);      
  437.      SetDlgItemText(hDlg, IDD_FNAME, szFileSpec);
  438.            return TRUE;
  439.  
  440.      Remember,  this is the  first thing that  happens to the  dialog box. Right
  441.      away we jump  into three commands  that haven't been discussed  before. Two
  442.      are related, and I'll discuss them first:
  443.  
  444.         SendDlgItemMessage(hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L);
  445.  
  446.      SendDlgItemMessage  sends a message to a  specific control in a dialog box,
  447.      identified by, in this case, the IDD_FNAME control ID. 
  448.      SendDlgItemMessage does not return until the message has been
  449.      processed. 'EM_LIMITTEXT, 80' sets  the control up for  receiving up to  80
  450.      characters of text, and the 0L is an empty lParam value for the
  451.      call. The bottom line is that this call did one thing: it set the
  452.      length of the text box to be 80 characters.
  453.  
  454.         SetDlgItemText(hDlg, IDD_FNAME, szFileSpec);
  455.  
  456.      SetDlgItemText sets the  title or text of a control in a dialog box. In our
  457.      case, it is the same control as the last call, and this time we send it the
  458.      "*.EXE" default file spec from above.
  459.  
  460.      Now the fun one:
  461.  
  462.         DlgDirList(hDlg, szFileSpec, IDD_FLIST, IDD_FPATH, wFileAttr);
  463.  
  464.      DlgDirList  fills a list  box with a  file or directory  listing. What gets
  465.      displayed is controlled by the parameters passed in: szFileSpec and
  466.      wFileAttr, both discussed above. IDD_FLIST is the ID of the listbox control
  467.      itself,  and IDD_FPATH is the  ID of a static control  that will be used by
  468.      Windows to  display the  current  drive and  directory. If  this  is 0,  no
  469.      display will be done.
  470.  
  471.      If the filespec is a directory name  (or a null string), the string will be
  472.      changed to "*.*". After the box is filled, the filespec  is stripped of any
  473.      drive or path information.
  474.  
  475.      At  this point,  the dialog  box is  up, and  the listbox  is full  of file
  476.      listings, and the user can move around in there just like any other Windows
  477.      file open box. 
  478.  
  479.  
  480.      Mouse Messages
  481.  
  482.                                         - 9 -
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.                    
  490.  
  491.      This brings us to  the fun part of the  dialog box code. Of course  we want
  492.      OUR dialog box  to be just  like everyone elses,  so double clicks  select,
  493.      etc. But then we have to write that code! So here goes(taken liberally from
  494.      Charles Petzold's Great book "Programming Windows"):
  495.  
  496.         case WM_COMMAND :
  497.            switch (wParam)
  498.               {
  499.               case IDD_FLIST :
  500.                  switch (HIWORD(Lparam))
  501.                     {
  502.                     case LBN_SELCHANGE :
  503.                        ----code below----
  504.                        return TRUE;
  505.  
  506.                     case LBN_DBLCLK :
  507.                        ----code below----
  508.                        return TRUE;
  509.                     }
  510.                  break;
  511.  
  512.      WM_COMMAND  is  the  workhorse message  of  Windows.  A  window receives  a
  513.      WM_COMMAND  just about anytime the user does something. If the user selects
  514.      a menu item, or a child control sends a note back to 'mom'. In our case, we
  515.      are  concerned about  messages coming  from the  list box,  so we  look for
  516.      IDD_FLIST, our ID for the listbox.
  517.  
  518.      If we receive a message from IDD_FLIST, we are likely to get two things: 1)
  519.      we select an item by single-clicking it with the mouse, or 2) we
  520.      double-click  something to  not only  select it,  but SELECT  it  (in other
  521.      words, do something with it now,  I only have enough time to deal  with the
  522.      mouse).
  523.  
  524.      This kind of information is passed to the window  in the high-order word of
  525.      Lparam. This is officially called 'wNotifyCode'.  If the message is from  a
  526.      control, this  will be a  Windows-type message. If  the message is  from an
  527.      accelerator, wNotifyCode is 1, and if from a menu, it is 0.
  528.  
  529.      This is why  there is a secondary switch case inside  the outer one. Now we
  530.      have to deal with what is going on with the listbox. Consequently, we  have
  531.      our two messages: 1) LBN_SELCHANGE, and 2) LBN_DBLCLK. 
  532.  
  533.  
  534.      LBN_SELCHANGE
  535.                   
  536.  
  537.         if (DlgDirSelect(hDlg, szFileName, IDD_FLIST))
  538.            lstrcat(szFileName, szFileSpec);
  539.         SetDlgItemText(Hdlg, IDD_FNAME, szFileName);
  540.  
  541.  
  542.                                         - 10 -
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.      DlgDirSelect assumes that the listbox  identified with the ID (in our  case
  550.      IDD_FLIST), has  been filled with a DlgDirList  function (good thing we did
  551.      that), and returns us the selection currently selected. The second
  552.      parameter should be  a pointer to  a 128-byte character  string (to be  fer
  553.      sure, fer sure). By the way, I will change this to 128 bytes before anybody
  554.      else sees it, now that I have looked that one up.
  555.  
  556.      The  function returns  non-zero  if successful,  zero  otherwise. And,  the
  557.      string stuffed into, in our case szFileName, will be a drive letter, or a
  558.      directory name, with any brackets, etc. removed. The function appends a ':'
  559.      to a drive letter and a '\' to a subdirectory name.
  560.  
  561.      So,  when we start out,  szFileSpec is *.EXE,   and if we  select [-c-] for
  562.      example, in this loop we concat c: with *.EXE, and send C:*.EXE to
  563.      IDD_FNAME with the SetDltItemText call that is next. Notice this doesn't do
  564.      anything  more than save the names in  the global strings, and display them
  565.      in the text box. However:
  566.  
  567.  
  568.      LBN_DBLCLK
  569.                
  570.  
  571.          if (DlgDirSelect(hDlg, szFileName, IDD_FLIST))
  572.             {
  573.             lstrcat(szFileName, szFileSpec);
  574.             DlgDirList(hDlg, szFileName, IDD_FLIST, IDD_FPATH, wFileAttr);      
  575.      SetDlgItemText(hDlg, IDD_FNAME, szFileSpec);
  576.             }
  577.          else
  578.             {
  579.             SetDlgItemText(hDlg, IDD_FNAME, szFileName);
  580.             SendMessage(hDlg, WM_COMMAND, IDOK, 0L);
  581.             }
  582.  
  583.      The first if message is identical. If we get a good return from
  584.      DlgDirSelect,  concat the  name,  and then...oh  yeah,  now we  need  to do
  585.      something,  since we double clicked!!  Ok, so what would we  like it to do?
  586.      Most  of us  would agree  that leaving  the szFileSpec  alone,   *.EXE, and
  587.      changing  to the drive  or directory, in  addition to changing  the text in
  588.      IDD_FNAME would be nice. 
  589.  
  590.      So that's what we  do. The second half is  identical to what we did  in the
  591.      LBN_SELCHANGE  message, just display, but the first  part is handled by re-
  592.      executing  the DlgDirList  call,  only passing  it  the new  szFileName  we
  593.      concatenated.
  594.  
  595.      This is  all well and  good if we  double click on  a directory or  a drive
  596.      letter, but what if we double click a file name? That's what the  else case
  597.      is for. Remember above I said that a good  return from DlgDirSelect gave us
  598.      a drive or subdirectory name? Well, a FALSE return gives us a filename. So,
  599.      if we  take the 'else'  clause, for FALSE, we  know that szFileName  is the
  600.      filename that the user double-clicked, and we stuff that into the IDD_FNAME
  601.  
  602.                                         - 11 -
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.      box, followed by sending OURSELVES (!!) an IDOK message.
  610.  
  611.  
  612.      IDD_FNAME
  613.               
  614.  
  615.      IDD_FNAME is also user-modifiable, so if the user types something in there,
  616.      we want to know what is going on, so we handle calls originated from there:
  617.  
  618.         if (HIWORD(lParam) == EN_CHANGE)
  619.            EnableWindow(GetDlgItem(hDlg, IDOK),
  620.              (BOOL) SendMessage(LOWORD(lParam), WM_GETTEXTLENGTH, 0, 0L));
  621.  
  622.      Remember  above  in talking  about messages  from  child controls,  how the
  623.      message is passed in the high-order word of lParam?, well here we go again.
  624.      And, this time we are looking for a changed text box, or EN_CHANGE. If this
  625.      is the case, Windows has already updated the text in the box.
  626.  
  627.      The EnableWindow line  is a combination of three  windows functions, and as
  628.      such is extremely messy. The EnableWindow call really looks like:
  629.  
  630.         EnableWindow(hwnd, fEnable), 
  631.  
  632.      where  hwnd is the handle of the window to be enabled or disabled according
  633.      to the Boolean equivalence of fEnable (ie, TRUE/FALSE).
  634.  
  635.      The window  we want to enable/disable  is the one whose  handle is returned
  636.      from  GetDlgItem(hDlg,  IDOK). hDlg  is the  handle to  our dialog  box, so
  637.      that's easy, but  how about the IDOK? Go back to  the .DLG file and look at
  638.      what  happens if the  user clicks the  button "Select". The  button returns
  639.      IDOK. It works  the same  as an  OK button, but  has Select  written on  it
  640.      instead. That is the window whose handle we are going after for the
  641.      EnableWindow call.
  642.  
  643.      Now, what are we going to do with it? 
  644.  
  645.         SendMessage(LOWORD(lParam), WM_GETTEXTLENGTH, 0, 0L)
  646.  
  647.      SendMessage is going  to send  the command WM_GETTEXTLENGTH  to the  window
  648.      whose handle is  the LOWORD of  lParam. The high  word was discussed  above
  649.      (twice) as the  message sent,  the low word  is the handle  of the  control
  650.      sending the message. Therefore, SendMessage is going to send a
  651.      WM_GETTEXTLENGTH command to the IDD_FNAME box which will return the length,
  652.      in bytes of the text in IDD_FNAME. 
  653.  
  654.      Whew...let's see now: if we square the result, oops wrong article.
  655.  
  656.      But, it's almost that  complicated. The bottom line is we are going to send
  657.      an EnableWindow message to the Select  button only if there is text  in the
  658.      IDD_FNAME  box after it has been modified. This will end up working its way
  659.      back to us as an IDOK, and will select the filename. 
  660.  
  661.  
  662.                                         - 12 -
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.      Now wasn't that fun?
  670.  
  671.  
  672.      IDOK
  673.          
  674.  
  675.      The IDOK message handler does the following:
  676.  
  677.         1) Gets the filename from IDD_FNAME. We put it there, remember?
  678.         2) If szFileName ends in ':' or '\', append szFileSpec to  
  679.            szFileName.
  680.         3) If szFileName ends in a wildcard, execute DlgDirList with the new    
  681.       szFileName, and clean up the displays appropriately:
  682.  
  683.            a) copy szFileName to szFileSpec (since it had a wildcard anyway)    
  684.       b) write the new szFileSpec into IDD_FNAME
  685.            c) if DlgDirList fails, beep to the user
  686.            d) exit the message loop
  687.  
  688.         4) If szFileName does not end in a wild-card, concat '\szFileSpec' onto 
  689.          szFileName, and re-execute DlgDirList with this new filename.
  690.  
  691.         5) If DlgDirList finishes successfully, displays are updated, and we    
  692.        exit the message loop
  693.  
  694.         6) If DlgDirList does not finish successfully, it  means that the       
  695.      szFileName did  not contain a  drive\directory structure. So,  it is       
  696.      probably a file name. This  is our back-door, so to speak, to get       the
  697.      file name.
  698.  
  699.         7) If we've come this far, we assume we have a full file-spec on our    
  700.       hands.
  701.  
  702.         8) We take two tries at opening the file with OF_EXIST set. This will   
  703.        open and close  the file just to  check for existence of  the file.      
  704.      The OF_READ  for read-only was thrown in  as insurance. The first try      
  705.      is with the  name we have  already. If that  fails, we try  with the       
  706.      default file extension on it, just in case. If both  fail, we beep       to
  707.      the user and exit.
  708.  
  709.         9) If we are successful  in opening and closing the file, we have       
  710.      finished what we set out to do, and exit the dialog box. The 
  711.            filename is copied from the OFSTRUCT way back up where the 
  712.            adventure started with File/Open, and at the bottom of that loop,    
  713.       we print  execute a MessageBox call  with the filename as  the child      
  714.      window text.
  715.  
  716.      I did  gloss over one  of Petzold's  routines, and neglected  to mention  a
  717.      couple of other things.  Petzold used an internal routine  called 'lstrchr'
  718.      to find the existence of a character in a string. That's how we decided  if
  719.      there was a wild-card in the filename. He also used lstrcat and 
  720.      lstrcpy to let Windows handle the far pointer manipulation without 
  721.  
  722.                                         - 13 -
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.      messing up.
  730.  
  731.      I know I've gone over the last part pretty quickly, but I tried to cover it
  732.      completely.  It's mostly  'C' code,  and  doesn't have  a  lot of  Windows-
  733.      particular stuff  in it. I  think I'd rather  spend my time  explaining the
  734.      hairy Windows parts than mess so much with the 'C' parts.
  735.  
  736.  
  737.      EndDialog
  738.               
  739.  
  740.      That's it for now.  As I have said, Please hang in there. If you are beyond
  741.      the scope of this article, stick with me we are going to go places 
  742.      together. If  you are  way beyond  this, write  us an article.  If you  are
  743.      bogged down, just  compile it, and  stare at the source.  If you want  help
  744.      with something, send me a note.
  745.  
  746.      Next month, unless I get mail not in  favor of it, we're going to put  this
  747.      month's code into a  DLL so we can use it later. Feel free to contact me in
  748.      any  of the  ways below.   Thanks  to those  of you  that have  e-mailed me
  749.      questions, keep them coming.   Notice that I now have an  internet address,
  750.      to make it real easy to get in touch  with me. I want to rat out the things
  751.      other people are having questions about,  not just what I think people want
  752.      to hear.
  753.  
  754.      Dave Campbell 
  755.         WynApse PO Box 86247 Phoenix, AZ 85080-6247 (602)863-0411    
  756.         wynapse@indirect.com
  757.         CIS: 72251, 445
  758.         Phoenix ACM BBS (602) 970-0474 - WynApse SoftWare forum
  759.  
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.                                         - 14 -
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.            Programming Techniques For Creating Windows Text File Editors  
  790.                                    by Eric Grass  
  791.        
  792.           This article  discusses advanced  programming techniques for  creating
  793.      text editors under Windows.  The  Edit window class will not be implemented
  794.      in order to focus on how to create more advanced types of editors.  We will
  795.      thus be creating a text editor "from scratch", so to speak.  As an example,
  796.      the source  code for a simple  text editor named EditPro  has been included
  797.      with this  issue of WPJ.   EditPro is a  smaller version of  another editor
  798.      named KeyPro which I wrote recently. 
  799.  
  800.           EditPro  simply loads and displays files using the Windows system font
  801.      and does paging.  This article covers  these aspects of  file editing,  and
  802.      then offers some tips on using the system caret. 
  803.  
  804.           The fundamental  portions of the program (i.e.,  the WinMain function,
  805.      etc.) were created using QuickCase:W for Windows.  The source code contains
  806.      some  in-line  assembly language  code in  order  to improve  the program's
  807.      execution time in certain places where it is appropriate.  
  808.  
  809.           I compiled  EditPro using QuickC for  Windows. You may or  may not get
  810.      the following warnings when you compile:  
  811.        
  812.           qcw /AS /G2w /Zp /W3 /D_WINDOWS /Gi /Od /Zi -f A:\EDITPRO.C 
  813.           A:\EDITPRO.C(190) : warning C4059: segment lost in conversion
  814.           A:\EDITPRO.C(191) : warning C4059: segment lost in conversion
  815.           A:\EDITPRO.C(195) : warning C4059: segment lost in conversion
  816.           A:\EDITPRO.C(198) : warning C4059: segment lost in conversion
  817.           A:\EDITPRO.C(200) : warning C4059: segment lost in conversion
  818.           A:\EDITPRO.C(208) : warning C4059: segment lost in conversion
  819.           A:\EDITPRO.C(254) : warning C4059: segment lost in conversion
  820.           linkw /ST:5120 /A:16 /CO @$$QCW$$.CRF
  821.           rcw -t EDITPRO.RES EDITPRO.EXE
  822.           cvpackw EDITPRO.EXE
  823.           EDITPRO.EXE - 0 error(s), 7 warning(s)
  824.  
  825.      These  warnings can be ignored.  This  occurs because the code extracts the
  826.      offset from global  memory pointers.  I  tried to figure  out a way to  use
  827.      casting to avoid these warnings, but I couldn't.  
  828.           The source code includes some helper routines (or, file routines) in a
  829.      file named filerout.c.  The procedure FileRoutine() merely invokes the Open
  830.      dialog box  and retrieves a  file path name.   The second  two routines are
  831.      used to merely display message boxes.  
  832.        
  833.      Storing Text  
  834.        
  835.           The  most important step in  designing a file  editor is designing the
  836.      data structure  for  storing the  lines  of text  of  the file  in  memory.
  837.      EditPro uses the following Line structure to store a single line of
  838.      text:
  839.                 _  
  840.                |                          ...........22222222222222  
  841.  
  842.                                         - 15 -
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.      OFFSET:------|           111111111122...........44444444555555  
  850.                |_   0123456789012345678901...........23456789012345  
  851.                \/\/|\________________________________________/  
  852.                 \ \ \      \  
  853.                  \ \ \      \__Text  
  854.                   \ \ \________(BYTE) total number of bytes in line structure  
  855.                    \ \_________(WORD) memory handle of next line  
  856.                     \__________(WORD) memory handle of previous line  
  857.        
  858.        
  859.           For each  line we allocate between  5 and 256 bytes  of global memory.
  860.      If a  line contains just  N characters, then we  only have to  allocate N+5
  861.      bytes.  Allocating more memory than this would be a waste  of memory. Thus,
  862.      this type of structure allows at  most 251 characters per line.  The  first
  863.      two bytes, bytes  0 and  1, store the  memory handle to  the previous  line
  864.      proceeding the current line.  The next two bytes, bytes 2  and 3, store the
  865.      memory  handle to the next  line following the current  line.  Thus, we may
  866.      construct  a linked list of  lines.  The byte at  offset 4 stores the total
  867.      number of bytes  constituting the memory block minus  1, and must therefore
  868.      be  a value between 4  and 255.   Finally, bytes 5 through  255 are used to
  869.      store the actual text  constituting the line.   The primary motivation  for
  870.      selecting the  value 256 as the  maximum size of  the Line Structure  is so
  871.      that we can  store the size  of the structure  (at byte  4) using just  one
  872.      byte.  
  873.  
  874.           The  file loading procedure can be expressed in pseudocode as follows:
  875.  
  876.  
  877.           .  
  878.           .  
  879.           .  
  880.           Open the specified file;  
  881.           if( size of file < MAXFILEBUFF)  
  882.                Allocate temporary file buffer of size = size of file;  
  883.           else  
  884.                Allocate a temporary file buffer of size = MAXFILEBUFF;  
  885.           Allocate and Lock a new Line Structure of size = 256 bytes;  
  886.           Set Line Structure pointer to 0;  
  887.           while( End of File not reached)  
  888.           {    Read portion of file into temporary file buffer;  
  889.                Set file buffer pointer to 0;  
  890.                while( Not at the end of the temporary file buffer)  
  891.                {    if( file buffer pointer points to Newline character)  
  892.                     {    Allocate and Lock new Line Structure of size 256 bytes;
  893.  
  894.  
  895.                          Store the handle of  the previous Line in the  new Line
  896.                          Structure;  
  897.  
  898.                          Reallocate the  size of the previous  Line Structure to
  899.                          N+5 bytes;  
  900.  
  901.  
  902.                                         - 16 -
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.                          Store  the  value  N+4 at  offset  4  in previous  Line
  910.                          Structure;  
  911.  
  912.                          Unlock the previous Line Structure;  
  913.                     }  
  914.                     else  
  915.                     {    Copy the character pointed to by file buffer pointer to
  916.                          the Line Buffer;  
  917.  
  918.                          Increment the  Line Buffer Pointer and  the file buffer
  919.                          pointer;  
  920.                     }  
  921.                }  
  922.           }  
  923.           Reallocate the size of the new Line structure to N+5 bytes;  
  924.           Store the size of  the new Line Structure (i.e.,  N+4) at offset 4  in
  925.           Line Structure;  
  926.           Unlock the new Line Structure;  
  927.           .  
  928.           .  
  929.           .  
  930.        
  931.        
  932.           The  corresponding source code is located in the file named editpro.c.
  933.      For EditPro, the value of MAXFILEBUFF is 0x00003FFFL bytes.  This value can
  934.      be made  larger, if desired, to  reduce the amount of  disk reads required.
  935.      If you look  at the source code, you'll notice that when line number 32,767
  936.      (7FFFH) is reached, EditPro displays a message notifying that the file will
  937.      be truncated at that point, because of Windows' scroll bar  
  938.      range limit of 32,767. Also,  when the user exits EditPro or  selects Close
  939.      from the  menu, we must  free the  memory associated with  all of the  Line
  940.      structures.
  941.        
  942.      Painting the Screen  
  943.        
  944.           Painting the screen involves drawing only a portion of the text in the
  945.      window.   Which portion is a drawn  depends on the line  which the user has
  946.      scrolled  to and  the  invalidated rectangle  specified by  the PAINTSTRUCT
  947.      structure that is filled out  by the BeginPaint() function.  To  output the
  948.      appropriate text  one  can  use either  the  TextOut()  or  TabbedTextOut()
  949.      function.  EditPro uses  the TabbedTextOut() function since it  must expand
  950.      the  tabs in  the file.  One thing  to  remember about  the TabbedTextOut()
  951.      function is  that it uses  up a  lot of CPU  cycles whenever it  is called.
  952.      Therefore,  you'll want  to call  this function  as few  times as  possible
  953.      whenever you're painting/repainting the screen.  To keep  track of the line
  954.      to which the  user has scrolled,  we use a  global variable,  hCurrentLine,
  955.      which holds the  memory handle of the Line  Structure of the line  to which
  956.      the user has scrolled.  This value is  set to the handle of the very  first
  957.      line when the file is first opened.  
  958.  
  959.           The  variable xoffset holds a non-positive value between 0 and -32,767
  960.      which determines the  text's displacement relative to the  x-axis.  This is
  961.  
  962.                                         - 17 -
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.      used  in case the window has been  horizontally scrolled by the user toward
  970.      the right.   xoffset is changed  (decreased) whenever the user  scrolls the
  971.      screen horizontally, and the window must be updated accordingly. 
  972.  
  973.           You'll notice  that the  text is  displayed in  the system  font. This
  974.      choice is purely arbitrary and can actually be any font that you want.  
  975.        
  976.      Paging The Screen  
  977.        
  978.           To page up/down, whenever  the user clicks the vertical scroll bar, we
  979.      merely  "chase pointers"  either  backwards or  forwards  from our  current
  980.      position in the file until we reach the  line that is at the bottom of  the
  981.      screen or at the top of the screen.  We use the client rectangle to help us
  982.      find  the  desired line.    Every  time we  chase  a  pointer  to the  next
  983.      consecutive line,  we  simply add  the  text height  of  that line  to  our
  984.      variable, CurrentLine, which initially is set to zero.  When CurrentLine is
  985.      greater  than the client rectangle's  top/bottom, then we  know we've found
  986.      the right line.  
  987.  
  988.           For  horizontal  paging,  we  merely  change  increment/decrement  the
  989.      xoffset variable and scroll the client window in the proper direction.  
  990.        
  991.      Tips On Using The Caret  
  992.        
  993.           The  topics covered thus far provide a minimum foundation for creating
  994.      editors. The  resulting editor  merely loads and  displays files.   What is
  995.      missing is the implemention of  the system caret into the program  and some
  996.      basic editing operations, which are topics I cannot cover in  depth in this
  997.      article due to  a limited amount of time. However, just  to get you started
  998.      on using the caret, here's a few tips:  
  999.        
  1000.           - The caret  is a shared resource. You must  create the caret whenever
  1001.           you're window receives the input focus, and destroy the caret whenever
  1002.           your  window loses input focus  (which is signaled  by the WM_SETFOCUS
  1003.           and WM_KILLFOCUS messages).  
  1004.  
  1005.           -  It is  important to  hide  the caret  before  erasing the  window's
  1006.           background. The WM_ERASEBKGND message signals when the background must
  1007.           be repainted. By  default (via the  DefWindowProc() function)  Windows
  1008.           paints the  background. If you  don't do  this, what  happens is  that
  1009.           occasionally the caret will leave an "imprint" on the window. That is,
  1010.           you'll  have two  carets appearing on  the screen, except  only one of
  1011.           them will actually be the caret and the other will be just an image of
  1012.           the caret.  
  1013.  
  1014.           The following code is  an example of how to hide  the caret before the
  1015.      background is repainted:  
  1016.        
  1017.                switch( wParam)  
  1018.                {   .  
  1019.                    .  
  1020.                    .  
  1021.  
  1022.                                         - 18 -
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.                    case WM_ERASEBKGND:  
  1030.                     // if window has input focus, hide the caret before
  1031.                     // erasing...  
  1032.                     if( hWnd == GetFocus())  
  1033.                     {    HideCaret( hWnd);  
  1034.                          dwTemp    =   DefWindowProc(hWnd,    Message,   wParam,
  1035.                                              lParam);  
  1036.                          ShowCaret( hWnd);  
  1037.                          return dwTemp;  
  1038.                     }  
  1039.                     else goto DEFAULTACTION;  
  1040.                    case WM_PAINT:  
  1041.                     .  
  1042.                     .  
  1043.                     .  
  1044.                    default:  
  1045.           DEFAULTACTION:   
  1046.      /* For  any message  for which you  don't specifically  provide a   */   /*
  1047.      service  routine, you should  return the message  to Windows    */   /* for
  1048.      default message processing.                             */              
  1049.      return DefWindowProc(hWnd, Message, wParam, lParam);  
  1050.                }  
  1051.                return 0L;  
  1052.        
  1053.           -  The  GetTextExtent() function  must be  used  to calculate  the new
  1054.           position of the caret whenever the user moves the caret.  
  1055.           - It's important to save the position of the caret before losing input
  1056.           focus  in  order  to know  where  to  display  the  caret again  after
  1057.           regaining input focus.  
  1058.  
  1059.        
  1060.      Closing Remarks  
  1061.        
  1062.           If time  permits,  I may  write another  article in  the future  which
  1063.      covers the caret and the implementation of basic editing operations.  
  1064.        
  1065.        
  1066.        
  1067.  
  1068.  
  1069.  
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.                                         - 19 -
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.                             Midlife Crisis: Windows at 32
  1090.                                     By Pete Davis
  1091.  
  1092.           I decided I  needed to back-track this month. Last month's article was
  1093.      done out of a sheer need for  me to know about threads and  synchronization
  1094.      without much thought given to you, the reader. I apologize. I'm going to do
  1095.      my best  to start from  the beginning on this  Win32 stuff and  explain the
  1096.      different  areas of Win32 programming. This month, in particular, I'm going
  1097.      to discuss  the differences between  the different environments,  Win32 for
  1098.      Windows 3.1, 'Chicago', and NT). This  difference is particularly important
  1099.      right  now as far as  the difference between NT and  Windows 3.1 when doing
  1100.      Win32 programming.
  1101.  
  1102.           One of  the  key  differences as  far  as environment  is  that  Win32
  1103.      applications  running  under  Windows  3.1 share  memory  with  Windows 3.1
  1104.      applications  and Win32  applications and  Win32 applications  share memory
  1105.      with other Win32 applications. This is from a virtual point of view, if you
  1106.      get  my meaning,  and it's  just what  we expect  from regular  Windows 3.1
  1107.      programs.  The difference is with  NT and later,  'Chicago'. Win32 programs
  1108.      running under  NT each have their  own virtual 4 GB  (that's gigabytes, for
  1109.      those of you not used to seeing  numbers of that magnitude) of RAM to  work
  1110.      in.  That means  that Program  Manager has  its own  4 GB  of RAM  and File
  1111.      Manager has its own 4 GB of RAM, even when they're both running at the same
  1112.      time. Actually, when I  say 4 GB, you're really  limited to a mere 2  GB of
  1113.      that memory.  The other  2 GB belongs  to the Kernel.  Also, keep  in mind,
  1114.      that's 'Virtual' memory,  not real memory. You're still limited by how much
  1115.      you have in your  machine and how big your swap file is. Under NT, you have
  1116.      only one swap file and its the permanent swap file.
  1117.  
  1118.           Anyway,  I  digress, the  point  is  that  without some  sort  of  IPC
  1119.      (interprocess  communication,  which  we'll  get  into  in  a  second),  NT
  1120.      applications wouldn't be  able to  see each other's  memory. This makes  it
  1121.      slightly  more difficult to share  memory between applications  but it pays
  1122.      off  in that one  process can't  damage another  process' memory  and cause
  1123.      everything to fall  to pieces. Instead, under NT, the  one process can hurt
  1124.      itself and die, but everything else goes on unaffected. 
  1125.  
  1126.           When  designing Win32  applications under  Windows 3.1,  however, it's
  1127.      important to keep in mind that the applications CAN wipe each other out. If
  1128.      you  want your applications to run under  both environments, you need to be
  1129.      sure to keep this in mind.  Under Windows 3.1, Win32 applications, like 16-
  1130.      bit  applications, share  the  same memory  with  all the  other  processes
  1131.      running. This can be  a problem when porting  Win32 applications to  Win32s
  1132.      that make assumptions about the memory.
  1133.  
  1134.           Well,  that's  enough of  that,  I think  you  get the  picture. Under
  1135.      Windows  3.1, 32-bit  apps share  the same memory,  under Windows  NT, they
  1136.      don't. Clear?
  1137.  
  1138.           Ok, so what if you want to share memory? Well, DDE is still there, but
  1139.      I wouldn't recommend it  for most situations. It's just too  much of a pain
  1140.      for most applications. The old method of using GlobalAlloc and then passing
  1141.  
  1142.                                         - 20 -
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.      the  handle  in  lParam  of  a  message  and the  other  application  using
  1150.      GlobalLock to access it no longer works because that 'Global'  memory isn't
  1151.      so  global anymore, it's not shared between applications (except in Win32s,
  1152.      but  we don't  want to  make that  assumption, right?).  In the  Windows NT
  1153.      environment, there are  memory-mapped files. These are  an excellent method
  1154.      of IPC  and the good news  is that Microsoft is working  on implementing it
  1155.      for Win32s  (that's 32-bit Windows  for Windows  3.1, as  opposed to  Win32
  1156.      which is  for NT  and Win32c for  'Chicago'). This  means there  will be  a
  1157.      simple, common method for sharing data between applications.
  1158.  
  1159.           I won't  go too in-depth into  it this month, but  memory-mapped files
  1160.      are essentially files that are treated as if they're regular memory, except
  1161.      a sort of temp file is created to  hold the data. The way it works is  that
  1162.      you have a file that you treat as if it's memory. You simply have a pointer
  1163.      that you can point  and move anywhere in the  file as if it were  a regular
  1164.      pointer to memory  and Win32 picks  up the tab on  the file I/O  work. It's
  1165.      basically just another type of virtual memory. All the other program has to
  1166.      know  about  is the  file mapping  object name.  There  are other  uses for
  1167.      memory-mapped files which I'll cover in a later column, likely one  devoted
  1168.      to memory-mapped files.
  1169.  
  1170.      Preemptive Multitasking vs. Non-Preemptive Multitasking
  1171.  
  1172.           Windows  NT  (and Windows  4.0,  when it  gets  here) is  a preemptive
  1173.      multitasking  operating   system.  You've  probably  seen  those  buzzwords
  1174.      mentioned in every review or discussion of NT. What does this mean exactly?
  1175.      Preemptive multitasking is where the CPU decides how much time your program
  1176.      has to run. After  that time is up,  your program is stopped,  the register
  1177.      contents  are saved and another program  is given control. And then another
  1178.      and  then another until it  gets back to the  first. Then its registers are
  1179.      reset and it is sent on its way for its particular time slice.
  1180.  
  1181.           Windows 3.x  use  a  non-preemptive  multitasking  system  where  each
  1182.      program is responsible for giving the other programs in the  system time to
  1183.      run. This  cooperation takes place in the  message queue where messages are
  1184.      passed around the system from one program to another until it finds its way
  1185.      to the program that needs it. In Windows 3.x it's simple to write a program
  1186.      that doesn't  release the CPU  to other  applications. Just try  writing an
  1187.      infinite loop and you've locked up the entire system.
  1188.  
  1189.           Under Windows  NT, the  message queue is  still used,  but the  system
  1190.      doesn't rely on  it to provide CPU time to other  programs. If your program
  1191.      has an  infinite loop,  then your  program will  lock up.  The rest of  the
  1192.      system will continue running with no effect from your program.
  1193.  
  1194.           I  should mention that Windows  3.x is not  an entirely non-preemptive
  1195.      multitasking  system.  There  are a  couple  parts  that  are, or  can  be,
  1196.      preemptive. The  DOS box, for example, is preempted by Windows. The DOS box
  1197.      receives its time slice to run  and that's it. Then Windows gets  some time
  1198.      for a while  and then it gives  another time slice to the  DOS box. Another
  1199.      place than can  be preemptive is VxDs  or .386 drivers. The  reason is that
  1200.      these  run at what is called  Ring 0. Ring 0 is  where the low-level system
  1201.  
  1202.                                         - 21 -
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.      control stuff takes  place in 386,  486 and now  Pentium chips. (There  are
  1210.      four  rings,  0-3. Rings  0  and 3  are  the  only ones  used  by Windows).
  1211.      Actually,  this  area  isn't  exactly  preemptively  multi-tasked  but   is
  1212.      available for it. The software running at Ring 0 has  complete control over
  1213.      the system, so it can really do whatever it wants.
  1214.  
  1215.           That's all for this month, I'm afraid. I'm really sorry if my articles
  1216.      seem a bit anemic for the next  few months. I'm afraid I have little choice
  1217.      in that. We'll see how much time I actually have over  the next few months,
  1218.      but this book is really going to take a lot of work.
  1219.  
  1220.  
  1221.  
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.  
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261.  
  1262.                                         - 22 -
  1263.  
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269.                                         WDASM
  1270.                            Review of a Windows Disassembler
  1271.                                     By Pete Davis
  1272.  
  1273.           WDASM is the only Windows disassembler  I know of that's available for
  1274.      shareware. The product is amazing and well worth it's mere $10 registration
  1275.      fee. The  version I  have  been using  is 1.2,  which  is the  unregistered
  1276.      version. I am awaiting version 1.6 which is on it's way.
  1277.  
  1278.           WDASM is available from many sources,  including the CompuServe WINSDK
  1279.      forum, WSMR-SIMTEL20.ARMY.MIL in the PD:<MSDOS.WINDOWS> directory, and from
  1280.      FTP.CICA.INDIANA.EDU in the pub/pc/win3/programr directory. 
  1281.  
  1282.           When you run  WDASM you get a window with a small and simple menu. The
  1283.      menu structure is:
  1284.  
  1285.      File          Edit         View            Help
  1286.      ----          ----         ----            ----
  1287.      Open          Set Bytes    Segment         Index
  1288.      Save Text As               Goto            About
  1289.      ----                       Address Offset
  1290.      Exit                       Far Call Names
  1291.  
  1292.  
  1293.           WDASM will  disassemble both .EXEs and  .DLLs. As soon as  you open an
  1294.      executable,  the WDASM  window shows  the disassembly  of Segment 1  of the
  1295.      executable. To change  to different segments, simply go to  View and select
  1296.      the segment you want. 
  1297.  
  1298.           Set Bytes  allows you to set  a range of bytes  to data, instructions,
  1299.      labeled instructions.
  1300.  
  1301.           Goto, of course, takes you  to a certain address. Address Offset  is a
  1302.      nice  feature. Normally, the only address offsets  that show up in the code
  1303.      are the labels. All labels are in the form:
  1304.  
  1305.                           LxxxxH: where xxxx is the offset.
  1306.  
  1307.           Far  call names  toggles between  labeling far  calls and  showing the
  1308.      actual address of the call.
  1309.  
  1310.           When you're  done  you can  use  Save Text  As  to save  the  assembly
  1311.      language code generated by WDASM to a .ASM file.
  1312.  
  1313.           There are some things  I'd like to  see in WDASM  and, in fact,  after
  1314.      talking  to Eric,  it appears  some of  them are  there (in  the registered
  1315.      version).  These include  some minor  bug fixes and  some expansion  of the
  1316.      program. I'd like to see a little commenting in the code about what's going
  1317.      on. Sometimes it's a simple operation to find out  what some code is doing.
  1318.      It would be nice if the disassembler did some of those for you.
  1319.  
  1320.           Also, I'd like to be able to do some editing in WDASM. For example, if
  1321.  
  1322.                                         - 23 -
  1323.  
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.      I figure out what a certain routine does, I'd  like to name it in WDASM and
  1330.      have it go through and correct all references to that label. 
  1331.  
  1332.           I'd like support  for the PE file  structure, which, actually,  when I
  1333.      suggested it to Eric, he was more than happy  to get some information on PE
  1334.      file structures from me and plans to upgrade the software to handle them.
  1335.  
  1336.           Other upgrades  which I'm aware  of that are  in the works  (or done?)
  1337.      include support  for 386/486  instructions and  support for  floating point
  1338.      instructions.
  1339.  
  1340.           I have  a wish list of things  to be added and I  have passed a lot of
  1341.      them to Eric. This is where Eric's product sticks out the most. I've talked
  1342.      to other shareware authors  about improvements in their products.  Few have
  1343.      been as receptive to new ideas as  Eric. Eric does his product for the end-
  1344.      user, not himself. That's really not as common as you might think. A lot of
  1345.      shareware authors  ask for your  comments and when  you send them  in, just
  1346.      ignore them. Eric really wants  to do a product that will be useful for his
  1347.      users. He's already done that. 
  1348.  
  1349.           I  can't recommend  this  program highly  enough.  If you  do  Windows
  1350.      disassembly,  consider  this program.  For  the  price,  it's  an  absolute
  1351.      bargain. And if you like  it, PLEASE REGISTER it.  It's only $10, which  is
  1352.      inexpensive, even for shareware. It's worth every penny.
  1353.  
  1354.           Happy disassembling.
  1355.  
  1356.      [Ed. Note: Just prior to  the release of this issue I  received Version 1.6
  1357.      of the disassembler. Not  enough time to really use it a  lot or to rewrite
  1358.      the  review. I will only  say that 1.6 has  some major improvements. I also
  1359.      know Eric is in the process of  making more. Get this disassembler and  try
  1360.      it out.]
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.                                         - 24 -
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.                               Hypertext, Sex and Winhelp
  1390.                                      By Loewy Ron
  1391.  
  1392.           Hi, this article  is about hypertext, help systems and winhelp. If you
  1393.      ask yourself what has this kind of article to do in a programming
  1394.      magazine,  and  tell yourself  (and  everyone around  you) that  you  are a
  1395.      programmer and not a technical writer, I can only tell you of a
  1396.      sentence I heard at  a recent conference I attended, from a  Rep. of a firm
  1397.      that markets a database development tool. The guy told us that
  1398.      in user surveys they learned that people that evaluated their
  1399.      product, gave the  quality of the documentation the same  weight they  gave
  1400.      to the functionality of the product. (Hearing this stuff, and 
  1401.      knowing I'm not as good as I should be at writing documentation, I 
  1402.      decided  I had to stop  while I'm at the  top - so this  is the end of this
  1403.      article, bye. Well,  no - this was  just a joke, we will  continue from now
  1404.      ..).
  1405.  
  1406.           An important part  of your application's documentation  is the on-line
  1407.      help. One of the advantages of programming for Windows, is that
  1408.      Windows includes a built-in help engine, with a (well?) documented
  1409.      interface. This engine is both easy for the users to use, standard
  1410.      among applications, and yet is powerful and extendible.
  1411.  
  1412.           This article  will talk a bit about  hypertext systems in general, and
  1413.      will try to focus on the Windows implementation.
  1414.  
  1415.           Hypertext is a term used to describe large amounts of textual data,
  1416.      that have embedded references to other textual elements of the
  1417.      database. These other  elements have  some connection to  the text  element
  1418.      that is currently read by the user, and might interest him. 
  1419.      The difference of hypertext systems from traditional documentation is  that
  1420.      reading a hypertext document, the  reader (user) can read in a non   linear
  1421.      order,  and  jump around  the  database  according  to  his will  (and  the
  1422.      references that were created in the document by the system's
  1423.      designer).
  1424.  
  1425.           We usually define  a piece of textual information that can be regarded
  1426.      as a single unit - a Topic. Our help "database" is a collection of
  1427.      Topics, that most (if not all) of them, have references (called
  1428.      Links) to other Topics, that have some connection to them.
  1429.  
  1430.           You have probably used some hypertext systems, such as the on-line
  1431.      help that came with your development package/language/compiler. (if
  1432.      you still use GW-BASIC as your main development tool - you are
  1433.      advised to upgrade, or you might find some of the other articles in
  1434.      this journal hard to follow).
  1435.  
  1436.           In order to incorporate help (using winhelp) into your application,
  1437.      you (roughly) have to go through the following steps :
  1438.  
  1439.      1. Design the layout of your hypertext help database.
  1440.  
  1441.  
  1442.                                         - 25 -
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449.      2. Create the winhelp source files, and compile them to create the
  1450.      .HLP file(s) for use with the winhelp application.
  1451.  
  1452.      3. Create a help  menu/button/toolbar or other interface element  from your
  1453.      application to the winhelp database, and code the winhelp API
  1454.      calls to activate that database from your application.
  1455.  
  1456.      4. Optionally - If you want to create context-sensitive help (help
  1457.      that is activated when a user presses the F1 key for example, and
  1458.      receives help about the operation/options that he is currently
  1459.      doing/having), code the key interception and calls to the winhelp
  1460.      database.
  1461.  
  1462.           Step 1 is really something that should be left to people that know
  1463.      more about user interfaces, usability studies and these sort of
  1464.      things than me. I have included some references that might be of
  1465.      interest at the end of this article.
  1466.  
  1467.           Steps 3 and 4 will be discussed in a future article (If the editor
  1468.      will want me to write any more after some angry readers will e-mail
  1469.      him some threats, or knock on his door at the middle of the night).
  1470.  
  1471.           In order to  create .HLP files - that contain  your help database, you
  1472.      have  to create  source  files for  Microsoft's  help compiler.  There  are
  1473.      actually 2 help compilers - HC30.EXE that creates help topics in
  1474.      Windows 3.0 format,  and HC31.EXE that creates  help topics in  Windows 3.1
  1475.      format.  While  HC31 help  databases can  be  more sophisticated  than HC30
  1476.      created databases, you will not be able to use them on Windows
  1477.      3.0 platforms, while winhelp that came with Windows 3.1 can display
  1478.      help from .HLP files in both formats.
  1479.  
  1480.           The  input to the help compiler is  a project description (.HPJ) file,
  1481.      and a set of Rich Text Format (.RTF) files, with special code to
  1482.      describe Topics, Links, Search keywords etc..
  1483.  
  1484.           RTF is a document description standard that can describe (any?)
  1485.      word-processor file using  only 7  bit characters. Unfortunately  RTF is  a
  1486.      language that is very hard to read and maintain manually. You would
  1487.      probably want to use a  word processor that can output RTF files, or a tool
  1488.      that can translate plain readable ascii files into RTF output.
  1489.      If you have Word for Windows, several help authoring templates,
  1490.      styles and macros are available in the commercial and shareware
  1491.      market, that can help in the creation of help databases. At the end
  1492.      of this  article you will find a  list of the help  authoring packages I am
  1493.      aware of, I have  not tried or used all  of them, I'm just trying  to bring
  1494.      them to your attention.
  1495.  
  1496.           In the RTF file, use page breaks between Topics. Your Topics can be
  1497.      longer than one page, but when you use a page break - you tell the
  1498.      Help Compiler that this is the end of the text that belongs to this
  1499.      Topic. For each Topic include a # and $ footnotes to describe its
  1500.      name, and reference, so that other topics will be able to include
  1501.  
  1502.                                         - 26 -
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.      Links to it. Links are included using a text with double underline
  1510.      attribute, followed by a hidden Topic reference name. I will give a
  1511.      RTF example that will help you understand the mechanism.
  1512.  
  1513.           We will define 2 Topics - TOP1 and TOP2 and create Links between
  1514.      them. The following code example is part of a RTF file. 
  1515.  
  1516.      {\f2
  1517.       #{\footnote \pard\plain \fs20 # TOP1}
  1518.       ${\footnote \pard\plain \fs20 $ TOP1}
  1519.      }
  1520.      \pard{This is the first paragraph of Topic 1, with no Link here}
  1521.      \pard{This is the 2nd. paragraph of topic 1, we will include a
  1522.      {\f2\uldb Link}{\v\f2 TOP2} here to Topic 2}
  1523.      \page
  1524.      {\f2
  1525.       #{\footnote \pard\plain \fs20 # TOP2}
  1526.       ${\footnote \pard\plain \fs20 $ TOP2}
  1527.      }
  1528.      \pard{This is Topic 2, Click {\f2\uldb Here}{\v\f2 TOP1} to reach
  1529.      topic 1 }
  1530.      \page
  1531.  
  1532.           As can be seen - Each topic starts with a # and $ footnotes, and
  1533.      ends with  a page break (\page). Whenever we want  to create a Link, we use
  1534.      the \uldb (double underline) attribute with the text we want to
  1535.      display, and follow  it with a hidden  (\v) text with the reference  to the
  1536.      Topic it is linked to.
  1537.  
  1538.           It should be explained at this point - that this code is not enough
  1539.      to create a help database that contains only these 2 Topics, it is,
  1540.      however, beyond the scope of this article to describe all the RTF
  1541.      commands needed  to create a help  document. I have, however,  included the
  1542.      source to a simple help database with only 3 Topics, and Links
  1543.      between them. You will have to refer to the RTF specifications
  1544.      (available from Microsoft, or - if  you have the MSDN CD-ROM, you  can find
  1545.      it there), and the help compiler documentation that comes with
  1546.      the SDK or with your compiler.
  1547.  
  1548.           The next file that should be created for the help compiler is the
  1549.      project file. The following code is an example of such a file :
  1550.  
  1551.      [OPTIONS]
  1552.      INDEX=TOP1
  1553.      COMPRESS=TRUE
  1554.      TITLE=Demo Help Project
  1555.  
  1556.      [FILES]
  1557.      DEMOPROJ.RTF
  1558.  
  1559.      [MAP]
  1560.  
  1561.  
  1562.                                         - 27 -
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.      [BITMAPS]
  1570.  
  1571.           This is a file that have a structure that resembles a .INI file,  with
  1572.      sections and options in it. The [OPTIONS] section include general
  1573.      options that are used by the help compiler during the .HLP file
  1574.      generation.  In  the example  above our  Topic 1  is  defined as  the index
  1575.      topic - the one that winhelp will display first when it loads the
  1576.      help file, the compress entry tells  the help compiler to compress the help
  1577.      text, and the title entry instructs winhelp what to display in
  1578.      the  title of the help window. It is important to notice that the .WPJ file
  1579.      syntax is  different between HC30 and  HC31. The example above  is good for
  1580.      HC30, and in HC31 the index entry should be replaced by a
  1581.      contents entry to achieve the same results.
  1582.  
  1583.           The [FILES] section lists all  the RTF source files used to  build the
  1584.      help database. There are additional sections and entries in section
  1585.      that are used to create and set options to the help database. It is
  1586.      advised that you refer to the Microsoft SDK documentation, or the
  1587.      documentation that came with your compiler for a complete discussion of all
  1588.      the features and options of the help project file.
  1589.  
  1590.      Summary
  1591.      -------
  1592.  
  1593.           O.k, this was just an introduction that touched the surface of what
  1594.      it means to create help databases for use with winhelp, and this
  1595.      should probably get you started. I might add additional articles on
  1596.      this subject in the future. Good luck, and have fun helping others.
  1597.  
  1598.           If  you wonder about the title of the  article - hey, this is my first
  1599.      one, and I covered 2 of the 3 subjects - that is pretty good, don't
  1600.      you think? 
  1601.  
  1602.      References :
  1603.      ------------
  1604.  
  1605.      1.  Microsoft Press - Microsoft Windows 3.1 Programming Tools, Chapter    3
  1606.      and Appendix B. 
  1607.  
  1608.      2. Borland Pascal With Objects 7.0 - Tools and Utilities Guide,
  1609.         Chapter 6 and Appendix A.
  1610.  
  1611.      3. Windows Help Authoring Guide - A Microsoft publication available
  1612.         on the internet as WHAG.ZIP in CICA.
  1613.  
  1614.      4. RTF Specifications - I have mine from the Microsoft MSDN CD-ROM.
  1615.  
  1616.      Help Authoring Tools :
  1617.      ----------------------
  1618.  
  1619.           This is a list of tools I know that exist. I have not used all of
  1620.      them, nor do I know if they all work. I only included this list in
  1621.  
  1622.                                         - 28 -
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.      order to help you  get a jump start in creating help  databases. All of the
  1630.      opinions I express - are mine, and mine only.
  1631.  
  1632.      1.  Microsoft  Windows Help Authoring Tools  - a combination of  a help    
  1633.      project editor  and winWord templates  and macros.  Available on  the      
  1634.      internet in CICA as WHAT.ZIP.
  1635.  
  1636.      2.  SYNTAX.ZIP - A tool to convert WP documents to windows help.
  1637.          Available in the misc directory of CICA on the internet.
  1638.  
  1639.      3.  HELP.ZIP - A tool to convert OS/2 IPF files to RTF documents.
  1640.          Available in the nt directory of CICA on the internet.
  1641.  
  1642.      4.  HAG.ZIP, WHAG.ZIP - Windows help authoring guide in winword and
  1643.          .HLP formats. Available in the programr directory of CICA.
  1644.  
  1645.      5.  WFWHLP.ZIP - Info on Constructing Windows Help Files.
  1646.          Available on  the program directory  of CICA,  also in CIS,  WINSDK    
  1647.      forum, Lib. #16.
  1648.  
  1649.      6.   HWAB21.ZIP - Help  Writer's Assistant for Windows  (This is cute).    
  1650.      Available on the util directory of CICA.
  1651.  
  1652.      7.  QDHELP.ZIP, QDTOOL.ZIP - Use DOS Editors  to Create WinHelp Files.     
  1653.      This is a really nice tool. Available on the util directory of
  1654.          CICA. Also on CIS WINSDK Forum, Lib 16.
  1655.  
  1656.      8.  DRHELPEV.ZIP - Macro to translate Word files to WinHelp files.
  1657.          Available on the winword directory of CICA.
  1658.  
  1659.      9.  HLPDK30.ZIP, HLPDK40.ZIP - My own Help Development Kit. I'm biased so I
  1660.      will not say  any further  word. Available on  SIMTEL hypertext  directory,
  1661.      GARBO programming  directory, Compuserve  WINSDK  forum, and  an  undefined
  1662.      place (currently in uploads) on CICA.
  1663.  
  1664.      10.  Doc-To-Help  - A  commercial tool.  A press  release  can be  found in
  1665.      D2HPRS.TXT and D2HNEW.ZIP in library 3 of the WINSDK forum on COMPUSERVE.
  1666.  
  1667.      11. HELP.DOT - WFW 2.0 Template for Creating WINHELP RTF Files -
  1668.          Library 3, WINSDK Forum, CIS.
  1669.  
  1670.      12. RoboHELP - A  Commercial Tool (I have heard  some nice things about    
  1671.      this one). HELPTO.TXT on CIS WINSDK forum (Lib 3) has a reference to it.
  1672.  
  1673.      13. BOOKHL.ZIP - Developing Online Help for Windows - The Book.
  1674.          WINSDK forum, Lib 16, CIS.
  1675.  
  1676.      14. CH102.ZIP - CreateHelp! HLP authoring tool.
  1677.          WINSDK forum, Lib 16, CIS.
  1678.  
  1679.      15. HCMAC1.ARC - HC1.DOT template and support files to build help.
  1680.          WINSDK forum, Lib 16, CIS.
  1681.  
  1682.                                         - 29 -
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689.           There are more tools and references in CIS WINSDK Forum, LIB 16, as
  1690.      well as other places.
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.  
  1724.  
  1725.  
  1726.  
  1727.  
  1728.  
  1729.  
  1730.  
  1731.  
  1732.  
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.                                         - 30 -
  1743.  
  1744.  
  1745.  
  1746.  
  1747.  
  1748.  
  1749.                              Enhancing the WINSTUB Module
  1750.                                    By Rodney Brown
  1751.                                          
  1752.           When I was reading over the first issue of WPJ, I came upon an article
  1753.      that was talking  about the possibilities of the WINSTUB  module.  This got
  1754.      me thinking and I started  working on enhancing WINSTUB.  WINSTUB is  a DOS
  1755.      program that is placed at the front  of your Windows application.  When you
  1756.      try to load  a Windows program from  DOS, it is the culprit  that gives you
  1757.      that nasty little  message "This program requires  Microsoft Windows," then
  1758.      drops you back to DOS to pay for your sin<g>.
  1759.  
  1760.           The first WINSTUB  program I designed automatically loaded  up Windows
  1761.      if the program was started from DOS.  I  then decided to change it a little
  1762.      bit because some users may not  like that.  The second WINSTUB module  asks
  1763.      the user whether they want to load  Microsoft Windows or exit to DOS.  This
  1764.      allows the user to back out of the program if they made a mistake in typing
  1765.      the program  name, etc..  The WINSTUB program  was written in Turbo C++ for
  1766.      DOS.  The source code and project file are provided in the WPJ archive, but
  1767.      the C++ code is discussed below for those with other C/C++ compilers.
  1768.  
  1769.  
  1770.      // Enhanced WINSTUB.EXE for Windows applications
  1771.  
  1772.      #include <process.h>
  1773.  
  1774.      The process.h header file  contains the information for the  spawn command,
  1775.      the spawn command allows you to call an external program.
  1776.  
  1777.      #include <stddef.h>
  1778.  
  1779.      This header file is used solely for the definition of the NULL statement.
  1780.  
  1781.      #include <iostream.h>
  1782.  
  1783.      This is the C++ version of stdio.h
  1784.  
  1785.      char answer;
  1786.      int returncode;
  1787.  
  1788.      These two  statements initialize an  answer variable  of type  char, and  a
  1789.      returncode variable of type int.
  1790.  
  1791.      int main(void)
  1792.      {
  1793.        cerr << "\nThis program requires Microsoft Windows to run.";
  1794.        cerr << "\nWould you like me to start Microsoft Windows for you? ";
  1795.  
  1796.      The cerr << "text" command is the C++ equivalent of sending text to stderr.
  1797.  
  1798.        cin >> answer;
  1799.  
  1800.      The  cin >> variable command is the  C++ equivalent of retrieving data from
  1801.  
  1802.                                         - 31 -
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.      stdin.
  1810.  
  1811.        if (answer == 'y' || answer == 'Y')
  1812.          {
  1813.            returncode = spawnlp(P_WAIT,"win.com","","myprog",NULL);
  1814.  
  1815.      The statement above  tries to call win.com  (Windows).  If the  call is not
  1816.      successful, the spawn  command returns a negative integer  number.  The "l"
  1817.      in spawnlp signifies that the  number of parameters sent to  called program
  1818.      is known.  The  "p" in spawnlp tells spawn  to search the DOS path  for the
  1819.      program being called.
  1820.  
  1821.            if (returncode<0)
  1822.              {
  1823.                cerr << "\n\nError, could not start Microsoft Windows.";
  1824.                cerr << "\nExiting back to DOS...";
  1825.              }
  1826.          }
  1827.        else
  1828.          cerr << "\n\nExiting back to DOS...";
  1829.  
  1830.        return returncode;
  1831.      }
  1832.  
  1833.      The purpose  of the  rest of  the program  should be  obvious, if  the user
  1834.      answered yes and the spanwnlp call  was not successful, an error message is
  1835.      displayed and the program drops back to DOS.  If the user answered  no, the
  1836.      program exits to DOS.
  1837.  
  1838.  
  1839.      Once you  have written and compiled  your DOS WINSTUB program,  you need to
  1840.      return to window and modify  your .def file to put everything together.   A
  1841.      sample .def file looks like this:
  1842.  
  1843.  
  1844.      NAME            MYPROG
  1845.      DESCRIPTION     'Description of program goes here...'
  1846.      EXETYPE         WINDOWS
  1847.      STUB            'WINSTUB.EXE'
  1848.      CODE            PRELOAD MOVEABLE
  1849.      DATA            PRELOAD MOVEABLE MULTIPLE
  1850.      HEAPSIZE        4096
  1851.      STACKSIZE       5120
  1852.  
  1853.  
  1854.      After reading the last 4 WPJ's, you should know what most of the above code
  1855.      does.  The main parameter we are concerned with  is the STUB parameter.  In
  1856.      Turbo C++ for Windows (and I assume Borland C++), the STUB parameter is not
  1857.      required unless you are using a WINSTUB module other than Borland's.  Turbo
  1858.      C++ for Windows also does not require the EXPORT parameter if you are using
  1859.      ObjectWindows.
  1860.  
  1861.  
  1862.                                         - 32 -
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.      There  are other possibilities  for WINSTUB, the  program above  was just a
  1870.      simple enhancement of  WINSTUB.  If you thought the  comments of the source
  1871.      code  above  was overkill,  I'm sorry,  but I  just  wanted to  explain the
  1872.      program to people who may not know C++, or are just starting out in C.
  1873.  
  1874.                                  About the author
  1875.  
  1876.      Rodney M. Brown is a civilian  employee at Charleston Air Force Base, South
  1877.      Carolina.  His job involves operating and maintaining minicomputers and POS
  1878.      Systems, programming and repairing microcomputers.   He also gives computer
  1879.      lessons to fellow employees.
  1880.  
  1881.      He can be reached through the following services:
  1882.  
  1883.      GEnie: R.BROWN141
  1884.  
  1885.      CompuServe: 72163,2165
  1886.  
  1887.      Internet: 72163.2165@compuserve.com
  1888.  
  1889.      If you  are connected  to more  than one  of these services,  communication
  1890.      through CompuServe is preferred.
  1891.  
  1892.  
  1893.  
  1894.  
  1895.  
  1896.  
  1897.  
  1898.  
  1899.  
  1900.  
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906.  
  1907.  
  1908.  
  1909.  
  1910.  
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921.  
  1922.                                         - 33 -
  1923.  
  1924.  
  1925.  
  1926.  
  1927.  
  1928.  
  1929.                              Microsoft Developers Network
  1930.                                     Dave Campbell
  1931.  
  1932.           How would you like to have all the latest information about Windows
  1933.      programming,  OLE, ODBC, etc. at your fingertips? This would include sample
  1934.      code from the people that wrote the compiler and defined the interface, and
  1935.      books  by leaders  in the industry.  So far  I'm talking  about 2-layers of
  1936.      documentation deep on my desk. 
  1937.  
  1938.           That's what I usually get  into when I get  rolling on my article,  or
  1939.      get  deep  into  a  development  sequence.  Sometimes  it   gets  downright
  1940.      embarrassing.
  1941.  
  1942.           There  is a solution, though. If you haven't heard about the Microsoft
  1943.      Developer's Network yet,  you're missing out on a valuable resource. I have
  1944.      had the pre-release CD since December, but didn't get a  CD-ROM drive until
  1945.      this month. This is the scenario: I got into Windows, then Word, and opened
  1946.      up  my article,  and my  source code.  Then back  to Resource  Manager, and
  1947.      opened  the CD. Now  for the rest of  the article, I  worked back and forth
  1948.      between  the two Windows applications, cutting  and pasting, and rewording,
  1949.      and basically saving me a ton of time.
  1950.  
  1951.           The Developer's Network  is a subscription program  in which Microsoft
  1952.      sends a CD out quarterly which uses a great user interface to search out
  1953.      information. The pre-release CD contains technical information and  example
  1954.      code to use in writing applications for C/C++, DDE, OLE, using the
  1955.      Clipboard.  NT and VB 2.0  sample code, VB  2.0 Professional documentation,
  1956.      Excel SDK, MAPI,  ODBC, and  RTF specifications.  Additionally you'll  find
  1957.      Charles  Petzold's Programming Windows 3.1 book  in its entirety, including
  1958.      code with hyperlinks out to the SDK. There's a few years worth of Microsoft
  1959.      Systems Journal  magazines, and Ray Duncan's  "Advanced MS-DOS Programming"
  1960.      book in its entirety.  When you open up a section of the CD for
  1961.      inspection,  you can view  the code, run  the executable, or  cut and paste
  1962.      directly into your application from the CD. 
  1963.  
  1964.           I think you get the idea.
  1965.  
  1966.           The installation  was  extremely  smooth...all  contained  on  the  CD
  1967.      itself. My CD-ROM  drive normally comes  alive as drive  I:, so I just  ran
  1968.      I:\SETUP.EXE. It is taking up about 10M of my hard disk because I let it do
  1969.      the most it wanted,  for speed of access  later. Once it was  finished, the
  1970.      whole thing was available for use. 
  1971.  
  1972.           The cost of the program is $200/yr now that the pre-release program is
  1973.      over. Petzold's  book alone is $50  if you buy high-dollar  retail, so that
  1974.      covered the cost of  the first one  for us in the  pre-release. I'm sure  I
  1975.      won't be disappointed with the remainder of them.
  1976.  
  1977.           Of course, you'll need a CD-ROM drive to play  the CDs, and that isn't
  1978.      cheap  yet. But, if you  know someone with a Gateway  2000 customer ID, you
  1979.      can buy a Sony drive, which is AX, CDI, multisession, and Kodak
  1980.      compatible, drive, cables, and interface card for $225 plus $5 shipping.  I
  1981.  
  1982.                                         - 34 -
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989.      highly recommend finding someone that can order this for you. I got mine in
  1990.      5 days, and it took about 20 minutes to install. It plays audio and digital
  1991.      CDs, and works great with the Developer's network.
  1992.  
  1993.           If you have any questions, feel free to send me e-mail:
  1994.  
  1995.      Dave Campbell 
  1996.         WynApse PO Box 86247 Phoenix, AZ 85080-6247 (602)863-0411    
  1997.         wynapse@indirect.com
  1998.         CIS: 72251,445
  1999.         Phoenix ACM BBS (602) 970-0474 - WynApse SoftWare forum
  2000.  
  2001.  
  2002.  
  2003.  
  2004.  
  2005.  
  2006.  
  2007.  
  2008.  
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017.  
  2018.  
  2019.  
  2020.  
  2021.  
  2022.  
  2023.  
  2024.  
  2025.  
  2026.  
  2027.  
  2028.  
  2029.  
  2030.  
  2031.  
  2032.  
  2033.  
  2034.  
  2035.  
  2036.  
  2037.  
  2038.  
  2039.  
  2040.  
  2041.  
  2042.                                         - 35 -
  2043.  
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049.                               Getting in touch with us:
  2050.  
  2051.      Internet and Bitnet:
  2052.  
  2053.      HJ647C at GWUVM.GWU.EDU -or- HJ647C at GWUVM.BITNET (Pete)
  2054.  
  2055.      GEnie: P.DAVIS5 (Pete)
  2056.  
  2057.      CompuServe: 71141,2071 (Mike)
  2058.  
  2059.      WPJ BBS (703) 503-3021 (Mike and Pete)
  2060.  
  2061.      You can also send paper mail to:
  2062.  
  2063.      Windows Programmer's Journal
  2064.      9436 Mirror Pond Drive
  2065.      Fairfax, VA   22032
  2066.            U.S.A.
  2067.  
  2068.           In future issues we  will be posting e-mail addresses  of contributors
  2069.      and columnists who  don't mind  you knowing their  addresses. We will  also
  2070.      contact any  writers from previous issues  and see if they  want their mail
  2071.      addresses made  available for you  to respond to  them. For now,  send your
  2072.      comments to us and we'll forward them.
  2073.  
  2074.  
  2075.  
  2076.  
  2077.  
  2078.  
  2079.  
  2080.  
  2081.  
  2082.  
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.                                         - 36 -
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.                                     The Last Page
  2110.                                    by Mike Wallace
  2111.  
  2112.           Some background:  Taoism is a  very old philosophy that originated  in
  2113.      China, and  one of its  major writers  was a  man named  Chuang-tse.   This
  2114.      month's column starts off with a story from his writings:
  2115.  
  2116.           Hui-tse said to Chuang-tse,  "I have a  large tree which no  carpenter
  2117.           can cut  into lumber.  Its  branches and trunk are  crooked and tough,
  2118.           covered with bumps and depressions.  No builder would turn his head to
  2119.           look at  it.  Your  teachings are the  same - useless,  without value.
  2120.           Therefore, no one pays attention to them."
  2121.  
  2122.           "As you know," Chuang-tse replied, "a cat is very skilled at capturing
  2123.           its prey.   Crouching  low, it  can leap  in  any direction,  pursuing
  2124.           whatever it  is after.    But when  its attention  is  focued on  such
  2125.           things, it can be easily caught with a net.  On the other hand, a huge
  2126.           yak  is not easily caught  or overcome.  It stands  like a stone, or a
  2127.           cloud in the sky.  But for all its strength, it cannot catch a mouse.
  2128.  
  2129.           "You complain that your tree is not valuable as lumber.  But you could
  2130.           make use of the shade it provides, rest under its sheltering branches,
  2131.           and stroll beneath it,  admiring its character and appearance.   Since
  2132.           it  would not  be  endangered  by  an axe,  what  could  threaten  its
  2133.           existence?  It is useless to you only because you want to make it into
  2134.           something else and do not want to use it in its proper way."
  2135.  
  2136.  
  2137.           Why am I writing about Taoism?  Well, I'm not, really.  I was reminded
  2138.      of this  story a couple of weeks  ago after reading a  review of IBM's OS/2
  2139.      2.1.  The  focus of the article  seemed to be  that OS/2 could run  Windows
  2140.      programs almost  as well as Windows.   Sounded like the  reviewer wanted to
  2141.      make OS/2 something it's not: Windows.  Thus, the story.  Now, I'm not here
  2142.      to  harp on  that useless  operating  system OS/2,  but if  I  want to  run
  2143.      Windows, I'm not going to buy a 486 with 12MB of RAM and a 100MB hard drive
  2144.      to support OS/2.  I've seen Windows run  fine on a 386 with 4MB and a  much
  2145.      smaller hard drive.  My computer could run OS/2, but I installed Windows NT
  2146.      on it, and it runs Win3.1 programs without a problem.  Windows NT has about
  2147.      the  same memory  requirement as  OS/2 but  needs less  space on  your hard
  2148.      drive.
  2149.  
  2150.           Windows and OS/2  are different  operating systems, and  I think  they
  2151.      were each designed with a different kind of end  user in mind.  If you want
  2152.      to run Windows, why buy OS/2?  OS/2 should have a better selling point than
  2153.      "it runs Windows apps almost as well as Windows."  Anyone buying OS/2 based
  2154.      on this  promise will only be  disappointed, I think.   An operating system
  2155.      should be able to  stand on what makes it  unique, or it will end  up being
  2156.      nothing more than a cheap imitation.
  2157.  
  2158.           Hey, enough ranting  and raving.  This  issue is already late  enough.
  2159.      Talk to you next month.
  2160.  
  2161.  
  2162.                                         - 37 -
  2163.  
  2164.  
  2165.  
  2166.